package com.example.gulimall.common.server;

import com.example.gulimall.common.config.mobile.SmsCodeAuthenticationSecurityConfig;
import com.example.gulimall.common.filter.BaseUsernamePasswordAuthenticateFilter;
import com.example.gulimall.common.handler.AuthenticationFailHandler;
import com.example.gulimall.common.handler.AuthenticationSuccessHandler;
import com.example.gulimall.common.handler.CustomAccessDeniedHandler;
import com.example.gulimall.common.perporties.SecurityProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;
/**
 * <p>@description: 资源服务器  </p>
 * <p>@author: JGD </p>
 * <p>@create: 2020/3/17 16:57 </p>
 * <p>@version : 2.0.0
 **/
@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {
    @Resource
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Resource
    private AuthenticationFailHandler authenticationFailHandler;
    @Resource
    private OAuth2WebSecurityExpressionHandler expressionHandler;
    @Resource
    private SecurityProperties securityProperties;
    @Resource
    private AuthenticationManager authenticationManager;
    @Autowired
    private SmsCodeAuthenticationSecurityConfig smsCodeAuthenticationSecurityConfig;
    @Override
    public void configure(HttpSecurity http) throws Exception {
        //设置创建session策略
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        //短信登录配置器
        http.apply(smsCodeAuthenticationSecurityConfig);
        //放行接口配置
        configAllowedRequestWithoutToken(http);
//        //所有请求必须授权
        rbacConfig(http);
        http.addFilterAt(baseUsernamePasswordAuthenticateFilter(), UsernamePasswordAuthenticationFilter.class);
        http.exceptionHandling().accessDeniedHandler(new CustomAccessDeniedHandler());
    }


    @Override

    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.expressionHandler(expressionHandler);

    }

    @Bean
    public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) {
        OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler();
        expressionHandler.setApplicationContext(applicationContext);
        return expressionHandler;
    }

    /**
     * 放行接口配置
     */
    private void configAllowedRequestWithoutToken(HttpSecurity http) throws Exception {
        //登录接口 放行
        http.authorizeRequests().antMatchers(securityProperties.getLoginUri()).permitAll();
        http.authorizeRequests().antMatchers(securityProperties.getLoginByMobileUri()).permitAll();

        //其它放行配置
        if (!securityProperties.getAllowedUri().isEmpty()) {
            for (String uri : securityProperties.getAllowedUri()) {
                http.authorizeRequests().antMatchers(uri).permitAll();
            }
        }
    }
    /**
     * rbac接口配置
     */
    private void rbacConfig(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().access("@rbacService.hasPermission(request,authentication)");

    }
    /**
     * 注册自定义的UsernamePasswordAuthenticationFilter
     */
    @Bean
    public BaseUsernamePasswordAuthenticateFilter baseUsernamePasswordAuthenticateFilter() {
        BaseUsernamePasswordAuthenticateFilter filter = new BaseUsernamePasswordAuthenticateFilter();
        filter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
        filter.setAuthenticationFailureHandler(authenticationFailHandler);
        filter.setFilterProcessesUrl(securityProperties.getLoginUri());
        filter.setAuthenticationManager(authenticationManager);
        return filter;
    }

}